package es.udc.pfc.davidparedes.model.task;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;

import es.udc.pfc.davidparedes.model.dao.GenericDaoHibernate;
import es.udc.pfc.davidparedes.model.storeservice.VendorAndMillisDTO;
import es.udc.pfc.davidparedes.model.userservice.TypeAndMillisDTO;
import es.udc.pfc.davidparedes.model.util.GlobalNames;

@Repository("taskDao")
public class TaskDaoHibernate extends
		GenericDaoHibernate<Task, Long> implements TaskDao {
	
	@SuppressWarnings("unchecked")
	public List<Task> findTasksByDate(Long userProfileId, Calendar startDate, Calendar endDate) {
		return getSession()
				  .createQuery(
				  "SELECT t FROM Task t WHERE "
				  + "t.vendor.userProfileId = :userProfileId AND "
				  + "t.start >= :startDate AND t.end <= :endDate ORDER BY t.start")
				  .setParameter("userProfileId", userProfileId)
				  .setCalendar("startDate", startDate)
				  .setCalendar("endDate", endDate)
				  .list();
	}

	@SuppressWarnings("unchecked")
	public List<Task> findUniverseTasksByDate(Long universeId,
			Calendar startDate, Calendar endDate) {
		return getSession()
				  .createQuery(
				  "SELECT t FROM Task t WHERE "
				  + "t.universe.universeId = :universeId AND "
				  + "t.start >= :startDate AND t.end <= :endDate ORDER BY t.start")
				  .setParameter("universeId", universeId)
				  .setCalendar("startDate", startDate)
				  .setCalendar("endDate", endDate)
				  .list();
	}

	@SuppressWarnings("unchecked")
	public List<Task> findUniverseTasksAtMoment(Long universeId,
			Calendar moment) {
		return getSession()
				  .createQuery(
				  "SELECT t FROM Task t WHERE "
				  + "t.universe.universeId = :universeId AND "
				  + "t.start <= :moment AND t.end >= :moment ORDER BY t.start")
				  .setParameter("universeId", universeId)
				  .setCalendar("moment", moment)
				  .list();
	}

	@SuppressWarnings("unchecked")
	public List<TypeAndMillisDTO> getVendorTasksDuration(Long userProfileId, Long universeId,
				Calendar startDate, Calendar endDate) {
		return getSession()
		  .createQuery(
		  "SELECT t.type as type, sum(t.duration) as millis FROM Task t WHERE "
		  + "t.vendor.userProfileId = :userProfileId AND "
		  + "t.universe.universeId = :universeId AND "
		  + "t.start >= :startDate AND t.end <= :endDate "
		  + "GROUP BY t.type")
		  .setParameter("userProfileId", userProfileId)
		  .setParameter("universeId", universeId)
		  .setCalendar("startDate", startDate)
		  .setCalendar("endDate", endDate)
		  .setResultTransformer(Transformers.aliasToBean(TypeAndMillisDTO.class))
		  .list();
	}

	@SuppressWarnings("unchecked")
	public List<VendorAndMillisDTO> getUniverseTasksDuration(Long universeId,
				Calendar startDate, Calendar endDate) {
		List<Character> taskTypes = new ArrayList<Character>();
		taskTypes.add(GlobalNames.TASK_ABSENTEEISM);
		taskTypes.add(GlobalNames.TASK_LOW);
		taskTypes.add(GlobalNames.TASK_VACATION);
		return getSession()
		  .createQuery(
		  "SELECT t.vendor as vendor, sum(t.duration) as millis FROM Task t WHERE "
		  + "t.universe.universeId = :universeId AND "
		  + "t.type NOT IN :types AND "
		  + "t.start >= :startDate AND t.end <= :endDate "
		  + "GROUP BY t.vendor")
		  .setParameter("universeId", universeId)
		  .setParameterList("types", taskTypes)
		  .setCalendar("startDate", startDate)
		  .setCalendar("endDate", endDate)
		  .setResultTransformer(Transformers.aliasToBean(VendorAndMillisDTO.class))
		  .list();
	}
	
}
